package com.example.demo.common.utils;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import javax.imageio.stream.FileImageOutputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
import java.util.regex.Pattern;

public class PhotoUtils {

    /**
     * 检查下输入的file是否为图片
     * @param file
     */
    public static String checkPhotoFile(MultipartFile file) {
        if(file==null){
            return "文件不存在";
        }
        String contentType = file.getContentType();
        String pattern = "^image/.+$";
        if(StringUtils.isBlank(contentType)
                ||!Pattern.matches(pattern, contentType)){
            return "不是图片格式";
        }
        String originalFilename = file.getOriginalFilename();
        String ext = originalFilename.substring(originalFilename.lastIndexOf("."));
        //jpg|jpeg|bmp|png
        Set<String> imgSet = new HashSet<String>();
        imgSet.add(".jpeg");
        imgSet.add(".jpg");
        imgSet.add(".bmp");
        imgSet.add(".png");
        if(!imgSet.contains(ext)){
            return "图片格式不对(格式要求jpg|jpeg|bmp|png)";
        }
        return "true";
    }

    /**
     * 强制压缩/放大图片到固定的大小
     *
     * @param w int 新宽度
     * @param h int 新高度
     */
    public void resize(int w, int h, String toPic,BufferedImage img) throws IOException {
        // SCALE_SMOOTH 的缩略算法 生成缩略图片的平滑度的 优先级比速度高 生成的图片质量比较好 但速度慢
        BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
        image.getGraphics().drawImage(img, 0, 0, w, h, null); // 绘制缩小后的图
        File destFile = new File(toPic);
        FileOutputStream out = new FileOutputStream(destFile); // 输出到文件流
        // 可以正常实现bmp、png、gif转jpg
        JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
        encoder.encode(image); // JPEG编码
        out.close();
    }

    /**
     * 构造函数
     */
    public BufferedImage imgCompress(String fileName) throws IOException {
        File file = new File(fileName);// 读入文件
        BufferedImage img = ImageIO.read(file);// 构造Image对象
        return img;
    }

    /**
     * 返回限制下最大的长宽
     * @param img
     * @param maxPhotoEdge
     * @return int[] [width,height]
     */
    public int[] getLastWH(BufferedImage img,int maxPhotoEdge){
        //BufferedImage src = ImageIO.read(srcFile);
        int width = img.getWidth();
        int height = img.getHeight();
        int maxEdge = Math.max(width, height);
        if(maxEdge<=maxPhotoEdge){
            return new int[]{width,height};
        }else{
            float ratio = (float)maxPhotoEdge / (float)maxEdge;
            int newWidth = (int)((float)width * ratio);
            int newHeight = (int)((float)height * ratio);
            return new int[]{newWidth,newHeight};
        }
    }

    public static byte[] getByteByPic(String imageUrl) throws IOException{
        File imageFile = new File(imageUrl);
        InputStream inStream = new FileInputStream(imageFile);
        BufferedInputStream bis = new BufferedInputStream(inStream);
        BufferedImage bm = ImageIO.read(bis);
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        String type = imageUrl.substring(imageUrl.length() - 3);
        ImageIO.write(bm, type, bos);
        bos.flush();
        byte[] data = bos.toByteArray();
        return data;
    }
    /**
     * 将图片压缩到指定大小以内
     *
     * @param srcImgData 源图片数据
     * @param maxSize 目的图片大小
     * @return 压缩后的图片数据
     */
    public static byte[] compressUnderSize(byte[] srcImgData, long maxSize) {
        double scale = 0.9;
        byte[] imgData = Arrays.copyOf(srcImgData, srcImgData.length);

        if (imgData.length > maxSize) {
            do {
                try {
                    imgData = compress(imgData, scale);

                } catch (IOException e) {
                    throw new IllegalStateException("压缩图片过程中出错，请及时联系管理员！", e);
                }

            } while (imgData.length > maxSize);
        }

        return imgData;
    }

    /**
     * 按照 宽高 比例压缩
     *
     * @param scale 压缩刻度
     * @return 压缩后图片数据
     * @throws IOException 压缩图片过程中出错
     */
    public static byte[] compress(byte[] srcImgData, double scale) throws IOException {
        BufferedImage bi = ImageIO.read(new ByteArrayInputStream(srcImgData));
        int width = (int) (bi.getWidth() * scale); // 源图宽度
        int height = (int) (bi.getHeight() * scale); // 源图高度

        Image image = bi.getScaledInstance(width, height, Image.SCALE_SMOOTH);
        BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

        Graphics g = tag.getGraphics();
        g.setColor(Color.RED);
        g.drawImage(image, 0, 0, null); // 绘制处理后的图
        g.dispose();

        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
        ImageIO.write(tag, "JPEG", bOut);

        return bOut.toByteArray();
    }

    //byte数组到图片
    public static void byte2image(byte[] data,String path){
        if(data.length<3||path.equals("")) return;
        try{
            FileImageOutputStream imageOutput = new FileImageOutputStream(new File(path));
            imageOutput.write(data, 0, data.length);
            imageOutput.close();
            System.out.println("Make Picture success,Please find image in " + path);
        } catch(Exception ex) {
            System.out.println("Exception: " + ex);
            ex.printStackTrace();
        }
    }

    /**
     * 文件保存方法1
     * @param file
     * @return filePath
     */
    public static String uploadImg(MultipartFile file) {
        if (null != file) {
            String myFileName = file.getOriginalFilename();// 文件原名称
            String ext = myFileName.substring(myFileName.lastIndexOf("."));
            String fileName = "test"+Constant.formatter2.get().format(new Date())+ext;
            String pat=Constant.tempSaveFolder;//获取文件保存路径
            Calendar cal = Calendar.getInstance();
            String sqlPath="photo/"+cal.get(Calendar.YEAR)+"/"+cal.get(Calendar.MONTH)+"/"+cal.get(Calendar.DAY_OF_MONTH)+"/";
            String savePath = pat+sqlPath;

            File fileDir=new File(savePath);
            if (!fileDir.exists()) { //如果不存在 则创建
                fileDir.mkdirs();
            }
            String path=savePath+fileName;
            File localFile = new File(path);
            try {
                file.transferTo(localFile);
                return sqlPath+fileName;
            } catch (IllegalStateException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }else{
            System.out.println("文件为空");
        }
        return null;
    }

    public static  byte[] readInputStream(InputStream inputStream) throws IOException {
        byte[] buffer = new byte[1024];
        int len = 0;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        while((len = inputStream.read(buffer)) != -1) {
            bos.write(buffer, 0, len);
        }
        bos.close();
        return bos.toByteArray();
    }

    /**
     * 下载文件1
     * @param urlStr
     * @param fileName
     * @throws IOException
     */
    public static void downloadFromUrl(String urlStr, String fileName) throws IOException{
        URL url = new URL(urlStr);
        HttpURLConnection conn = (HttpURLConnection)url.openConnection();
        conn.setConnectTimeout(10*1000);
        conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");

        InputStream inputStream = conn.getInputStream();
        //获取自己数组
        byte[] getData = readInputStream(inputStream);

        File file = new File(fileName);
        FileOutputStream fos = new FileOutputStream(file);
        fos.write(getData);
        if(fos!=null){
            fos.close();
        }
        if(inputStream!=null){
            inputStream.close();
        }

        System.out.println("info:"+url+" download success");

    }

    public static void main(String[] args) throws IOException {
        //压缩图片,从像素角度压缩
        String fromPic = "C:/Users/Administrator/Desktop/test3.jpg";
        String toPic = "C:/Users/Administrator/Desktop/test3"+new Date().getTime() +".jpg";
        PhotoUtils pu = new PhotoUtils();
        try {
            BufferedImage img = pu.imgCompress(fromPic);
            int[] wh = pu.getLastWH(img, 1500);
            pu.resize(wh[0],wh[1],toPic,img);
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("error:default to create file.");
        }
        System.out.println("操作成功。");

        //压缩图片，从大小角度压缩，每次压缩90%循环压缩
        long timeStart = System.currentTimeMillis();
        String imgLocalUrl = "E:\\tp\\abc.jpg";
        byte[] imgBytes = getByteByPic(imgLocalUrl);
        byte[] resultImg = compressUnderSize(imgBytes,800 * 1024);
        byte2image(resultImg,"E:\\tp\\timga.jpg");
        long timeEnd = System.currentTimeMillis();
        System.out.println("耗时："+ (timeEnd - timeStart));

    }

}
